package org.evil.deus.rss.service;

import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.net.HttpURLConnection;
import java.net.URL;

import org.evil.deus.rss.CursorUtils;
import org.evil.deus.rss.R;
import org.evil.deus.rss.parser.ItemsParser;
import org.evil.deus.rss.parser.ItemsParser.Channel;
import org.evil.deus.rss.parser.ItemsParser.Item;
import org.evil.deus.rss.provider.RSS;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

public class UpdateService extends Service {

	private static final String TAG = UpdateService.class.getSimpleName();
	private static final String NEWS_SELECTION = RSS.Item.TITLE + " = ? AND " + RSS.Item.LINK + " = ? AND " + RSS.Item.DATE + " = ?";
	private static final String CHANNELS_SELECTION = RSS.Channel.URL + " = ?";
	private static final String NEW_ITEMS_SELECTION = RSS.Item.CHANNEL + " = ? AND " + RSS.Item.STATE + " = ?";
	private static final int NOTIFICATION_ID = 1;

	private static final Intent OPEN_INTENT = new Intent();
	static {
		OPEN_INTENT.setComponent(new ComponentName("org.evil.deus.rss", ".ui.Reader"));
	}

	private class Updater implements Runnable {

		private ContentResolver contentResolver = null;
		private String url = null;

		public Updater(String url, ContentResolver resolver) {
			this.url = url;
			this.contentResolver = resolver;
		}

		public void run() {
			ItemsParser parser = new ItemsParser();
			HttpURLConnection connection = null;
			InputStream is = null;
			ContentValues contentValues = new ContentValues();
			try {
				URL uri = new URL(url);
				connection = (HttpURLConnection) uri.openConnection();
				connection.connect();
				if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
					is = connection.getInputStream();
					if(parser.parse(is)) {
						Channel channel = parser.getChannels()[0];
						ContentValues values = new ContentValues();
						values.put(RSS.Channel.TITLE, channel.getTitle());
						values.put(RSS.Channel.LINK, channel.getLink());
						values.put(RSS.Channel.DESCRIPTION, channel.getDescription());
						values.put(RSS.Channel.IMAGE, channel.getUrl());
						values.put(RSS.Channel.LANGUAGE, channel.getLanguage());
						contentResolver.update(RSS.Channel.CONTENT_URI, values, CHANNELS_SELECTION, new String[] { url });
						Item[] items = parser.getItems();
						if (items != null) {
							for (Item item : items) {
								Cursor cursor = contentResolver.query(	RSS.Item.CONTENT_URI,
																		null,
																		NEWS_SELECTION,
																		new String[] {
																		item.getTitle(),
																		item.getLink(),
																		String.valueOf(item.getPubDate())},
																		null);
								if (cursor.getCount() <= 0) {
									contentValues.clear();
									contentValues.put(RSS.Item.TITLE, item.getTitle());
									contentValues.put(RSS.Item.LINK, item.getLink());
									contentValues.put(RSS.Item.CATEGORY, item.getCategory());
									contentValues.put(RSS.Item.AUTHOR, item.getAuthor());
									contentValues.put(RSS.Item.DATE, item.getPubDate());
									contentValues.put(RSS.Item.DESCRIPTION, item.getDescription());
									contentValues.put(RSS.Item.STATE, 1);
									contentValues.put(RSS.Item.CHANNEL, url);
									contentResolver.insert(RSS.Item.CONTENT_URI, contentValues);
								}
								cursor.close();
							}
						}
					}
				}
			} catch (Exception e) {
				Log.e(TAG, "can't update news", e);
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
						Log.e(TAG, "can't close http input stream", e);
					}
				}
				connection.disconnect();
				stopSelf();
			}
		}
	}

	private class ChannelRefresher implements Runnable {
		WeakReference<Context> reference = null;

		public ChannelRefresher(Context context) {
			this.reference = new WeakReference<Context>(context);
		}

		public void run() {
			Thread current = null;
			Context context = null;
			if (reference != null && (context = reference.get()) != null) {
				ContentResolver contentResolver = context.getContentResolver();
				Cursor cursor = contentResolver.query(RSS.Channel.CONTENT_URI, null, null, null, null);
				if (cursor.moveToFirst()) {
					do {
						String url = CursorUtils.getString(cursor, RSS.Channel.URL);
						if (!TextUtils.isEmpty(url)) {
							current = new Thread(new Updater(url, contentResolver));
							current.start();
							try {
								current.join();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							Cursor items = contentResolver.query( RSS.Item.CONTENT_URI, 
																  null,
																  NEW_ITEMS_SELECTION, 
																  new String [] {url, String.valueOf(1)}, 
																  null);
							int count = items.getCount();
							items.close();
							if (count > 0) {
									NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
									long when = System.currentTimeMillis();
									Notification notification = new Notification(R.drawable.icon, context.getString(R.string.notification_ticker_message), when);
									PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, OPEN_INTENT, 0);
									notification.setLatestEventInfo(context, 
																	context.getString(R.string.notification_ticker_message), 
																	context.getString(R.string.notification_message) + " " + count, 
																	pendingIntent);
									notificationManager.notify(NOTIFICATION_ID, notification);
							}
						}
					} while (cursor.moveToNext());
				}
				cursor.close();
				Intent intent = new Intent(context.getString(R.string.action_sync_end));
				context.sendBroadcast(intent);
			}
		}
	}

	private Thread updateThread = null;

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		if (updateThread == null || !updateThread.isAlive()) {
			updateThread = new Thread(new ChannelRefresher(this));
			updateThread.start();
		}
		return super.onStartCommand(intent, flags, startId);
	}
}
